package com.smartboard.network.socket;

import android.util.Log;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * client端的socket
 * @author cheasonxie
 */
public class SocketClient {
    private static final String TAG = "SocketClient";

    private static final int MAX_QUEUE_SIZE = 10;

    private String mIp;
    private int mPort;
    private Socket mSocket = null;
    private BlockingQueue<Object> mSendDataQueue;
    private OnReceiveListener mRecvListener = null;

    public SocketClient(String ip, int port) {
        mIp = ip;
        mPort = port;
        mSendDataQueue = new ArrayBlockingQueue<>(MAX_QUEUE_SIZE);
    }

    public boolean open() {
        if(mSocket != null && !mSocket.isClosed())
            return true;
        try {
            mSocket = new Socket(mIp, mPort);
            startReadThread();
            startWriteThread();
            return true;
        } catch (IOException e) {
            Log.e(TAG, "fail to connect server:" + mIp + ", port:" + mPort);
            e.printStackTrace();
            return false;
        }
    }

    public void close() {
        try {
            if (mSocket != null && !mSocket.isClosed()) {
                mSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isClosed() {
        if(mSocket != null)
            return mSocket.isClosed();
        return true;
    }

    public void send(Object data) {
        try {
            mSendDataQueue.put(data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void setOnReceiveListener(OnReceiveListener listener) {
        mRecvListener = listener;
    }

    // 读数据线程
    private void startReadThread() {
        new Thread() {
            @Override
            public void run() {
                ObjectInputStream in = null;
                try {
                    in = new ObjectInputStream(mSocket.getInputStream());
                    while(!isClosed()) {
                        Object data = in.readObject();
                        if(data != null) {
                            Log.d(TAG, "receive object:" + data);
                            if(mRecvListener != null)
                                mRecvListener.onReceive(mSocket, data);
                        } else {
                            break;
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    if(in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }.start();
    }

    // 发送数据线程
    private void startWriteThread(){
        new Thread() {
            @Override
            public void run() {
                ObjectOutputStream out = null;
                try {
                    out = new ObjectOutputStream(mSocket.getOutputStream());
                    while(!isClosed()) {
                        Object data = mSendDataQueue.take();
                        Log.d(TAG, "send object:" + data);
                        out.writeUnshared(data);
                        Log.d(TAG, "send object ok...");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if(out != null) {
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }.start();
    }
}
